home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- ** **
- ** Module: QDUtils.c **
- ** **
- ** **
- ** Purpose: Utilities for creating Quickdraw windows and GWorlds **
- ** **
- ** Copyright (C) 1992-1995 Apple Computer, Inc. All rights reserved. **
- ** **
- ** **
- *****************************************************************************/
- #include <Script.h>
- #include <stdio.h>
-
- #include <Memory.h>
- #include <Quickdraw.h>
- #include <QDOffscreen.h>
- #include <Windows.h>
-
- #include "QD3D.h"
- #include "QDUtils.h"
-
- /******************************************************************************
- ** **
- ** Macros **
- ** **
- *****************************************************************************/
-
- /* a bad hack macro */
- #ifndef GetMBarHeight
- #define GetMBarHeight() (* (short *) 0x0BAA)
- #endif
-
- #define COPYRECT(srcRect, dstRect) { \
- *(long *)(dstRect) = *(long *)(srcRect); \
- ((long *)(dstRect))[1] = ((long *)(srcRect))[1]; \
- }
-
-
- /******************************************************************************
- ** **
- ** Forward Declarations **
- ** **
- *****************************************************************************/
-
- /*
- * A BIG NOTE:
- * The following functions really belong in application land but since we
- * share them as common functions in our Escher test programs they are
- * placed here into the Quickdraw library directory. Escher applications
- * should have similar functions that meet their own requirements.
- */
-
- static GDHandle GetGDeviceUsingDepth(
- unsigned long depth);
-
- static GDHandle FindDeviceFromWindow(
- WindowPtr window,
- PixMapHandle gPixMap);
-
- static void GetPortTopLeft(
- CGrafPtr port,
- Point *topLeft);
-
- static BitMap *BitsToMap(
- BitMap *bits);
-
- static void CopyPixels_32(
- GDHandle device,
- WindowPtr window,
- PixMapHandle hPixMap);
-
- /******************************************************************************
- ** **
- ** Functions **
- ** **
- *****************************************************************************/
-
- /*===========================================================================*\
- *
- * Routine: ErQDWindow_New()
- *
- * Comments: Create a Quickdraw window and return it. The window is
- * centered in the gdevice that has the specified depth or
- * the device with the greatest depth less than said depth.
- *
- * Notes: This is an applicatiion specific function.
- *
- \*===========================================================================*/
-
- WindowPtr QDWindow_New(
- Str255 name,
- unsigned long x,
- unsigned long y,
- unsigned long xSize,
- unsigned long ySize,
- unsigned long depth,
- TQ3Boolean autoCenter)
- {
- Rect deviceBounds;
- unsigned short xCenter;
- unsigned short yCenter;
- Rect where;
- GDHandle gDevice;
- WindowPtr window;
-
- gDevice = GetGDeviceUsingDepth(depth);
- deviceBounds = (*gDevice)->gdRect;
-
- if (autoCenter) {
- xCenter = deviceBounds.left + ((deviceBounds.right - deviceBounds.left)/2);
- yCenter = deviceBounds.top + ((deviceBounds.bottom - deviceBounds.top)/2);
- yCenter += (GetMBarHeight()/2);
-
- where.left = xCenter - (xSize/2);
- where.top = yCenter - (ySize/2);
- } else {
- where.left = x;
- where.top = y;
- }
-
- where.right = where.left + xSize;
- where.bottom = where.top + ySize;
-
- window = NewCWindow(nil,
- &where,
- name,
- true,
- documentProc,
- (WindowPtr) -1,
- false,
- 0);
- if (!window) {
- return (NULL);
- }
-
- SetPort(window);
-
- return (window);
- }
-
-
- /*===========================================================================*\
- *
- * Routine: GetGDeviceUsingDepth()
- *
- * Comments: Find the gdevice that best fits the depth argument. If not
- * found then return the first gdevice.
- *
- * Notes: This is an applicatiion specific function.
- *
- \*===========================================================================*/
-
- static GDHandle GetGDeviceUsingDepth(
- unsigned long depth)
- {
- GDHandle device; /* current device */
- GDHandle bestDevice; /* device close to matching depth */
- unsigned long bestDeviceNotFound; /* termination flag */
-
- bestDevice = device = GetDeviceList();
- bestDeviceNotFound = 1;
-
- while (bestDeviceNotFound && device) {
- /* only search on active screen devices */
- if (((*device)->gdFlags & (1 << screenActive)) == 0) {
- continue;
- }
-
- if ((*(*device)->gdPMap)->pixelSize == depth) {
- bestDevice = device;
- bestDeviceNotFound = 0;
- }
-
- device = GetNextDevice(device);
- }
-
- return (bestDevice);
- }
-
-
- /*===========================================================================*\
- *
- * Routine: ErQDGWorld_New()
- *
- * Comments: Create a Quickdraw window and return it. The window is
- * centered in the gdevice that has the specified depth or
- * the device with the greatest depth less than said depth.
- *
- * Notes: This is an applicatiion specific function.
- *
- \*===========================================================================*/
-
- GWorldPtr QDGWorld_New(
- unsigned long xSize,
- unsigned long ySize,
- unsigned long depth)
- {
- Rect rectGW;
- GWorldPtr gWorld;
- PixMapHandle hPixMap;
-
- SetRect(&rectGW, 0, 0, (unsigned short)xSize, (unsigned short)ySize);
- NewGWorld(&gWorld, depth, &rectGW, 0, 0, 0);
-
- if(gWorld == NULL)
- return(NULL);
-
- hPixMap = GetGWorldPixMap(gWorld);
- HLock((Handle)hPixMap);
-
- LockPixels(hPixMap);
-
- HUnlock((Handle)hPixMap);
-
- return (gWorld);
- }
-
-
- /*===========================================================================*\
- *
- * Routine: QDClearBackground()
- *
- * Comments:
- *
- * Notes: This is an applicatiion specific function.
- *
- \*===========================================================================*/
-
- void QDClearBackground(
- GWorldPtr gWorld,
- TQ3ColorRGB bgColor)
- {
- RGBColor qdBgColor;
- GrafPtr thePort;
-
- if (gWorld) {
- GDHandle oldGD;
- GWorldPtr oldGW;
-
- /* save current port */
- GetGWorld(&oldGW, &oldGD);
-
- SetGWorld(gWorld, NULL);
- qdBgColor.red = (unsigned short)(bgColor.r * 65535.0);
- qdBgColor.green = (unsigned short)(bgColor.g * 65535.0);
- qdBgColor.blue = (unsigned short)(bgColor.b * 65535.0);
- RGBBackColor(&qdBgColor);
- EraseRect(&gWorld->portRect);
-
- /* restore port */
- SetGWorld(oldGW, oldGD);
- } else {
- qdBgColor.red = (unsigned short)(bgColor.r * 65535.0);
- qdBgColor.green = (unsigned short)(bgColor.g * 65535.0);
- qdBgColor.blue = (unsigned short)(bgColor.b * 65535.0);
- RGBBackColor(&qdBgColor);
- GetPort(&thePort);
- EraseRect(&thePort->portRect);
- }
- }
-
-
- /*===========================================================================*\
- *
- * Routine: ErQDSwapBuffer()
- *
- * Comments: If there is a gWorld then copy from it to the window.
- *
- * Notes: This is an applicatiion specific function.
- *
- \*===========================================================================*/
-
- void QDSwapBuffer(
- WindowPtr window,
- GWorldPtr gWorld)
- {
- if (window && gWorld) {
- PixMapHandle hPixMap;
- GrafPtr savePort;
- RGBColor qdBgColor;
-
- GetPort(&savePort);
- SetPort(window);
-
- hPixMap = GetGWorldPixMap(gWorld);
- HLock((Handle)hPixMap);
-
- qdBgColor.red = (unsigned short)65535;
- qdBgColor.green = (unsigned short)65535;
- qdBgColor.blue = (unsigned short)65535;
- RGBBackColor(&qdBgColor);
-
- /* myGDevice = FindDeviceFromWindow(window, hPixMap); */
- /* CopyPixels_32(myGDevice, window, hPixMap); */
- CopyBits((BitMapPtr)(*hPixMap),
- (BitMapPtr) &window->portBits,
- (Rect *) &(*gWorld).portRect,
- (Rect *) &window->portRect,
- (short)srcCopy, (RgnHandle)NULL);
-
- HUnlock((Handle)hPixMap);
-
- SetPort(savePort);
- }
- }
-
- /*===========================================================================*\
- *
- * Routine: CopyPixels_32()
- *
- * Comments:
- *
- \*===========================================================================*/
-
- static void CopyPixels_32(
- GDHandle device,
- WindowPtr window,
- PixMapHandle hPixMap)
- {
- long w, width, height;
- Point upperLeft;
- Rect deviceBounds;
- long offsetX, offsetY;
- unsigned long *srcPtr, *srcStart, *dstPtr, *dstStart;
- long srcRowBytes, dstRowBytes;
-
- width = (*hPixMap)->bounds.right - (*hPixMap)->bounds.left;
- height = (*hPixMap)->bounds.bottom - (*hPixMap)->bounds.top;
-
- upperLeft.v = window->portRect.top;
- upperLeft.h = window->portRect.left;
- LocalToGlobal(&upperLeft);
-
- deviceBounds = (*device)->gdRect;
- offsetX = upperLeft.h - deviceBounds.left;
- offsetY = upperLeft.v - deviceBounds.top;
-
- srcRowBytes = (*hPixMap)->rowBytes & 0x3FFF;
- dstRowBytes = (*(*device)->gdPMap)->rowBytes & 0x3FFF;
-
- srcStart = (unsigned long *)(*hPixMap)->baseAddr;
-
- dstStart = (unsigned long *)((unsigned char *)((*(*device)->gdPMap)->baseAddr) +
- (offsetY * dstRowBytes) + (offsetX << 2));
-
- while (--height >= 0) {
- w = width;
-
- srcPtr = srcStart;
- dstPtr = dstStart;
-
- while (--w >= 0) {
- *dstPtr++ = *srcPtr++;
- }
-
- srcStart = (unsigned long *)((unsigned char *)srcStart + srcRowBytes);
- dstStart = (unsigned long *)((unsigned char *)dstStart + dstRowBytes);
- }
- }
-
- /*===========================================================================*\
- *
- * Routine: FindDeviceFromWindow()
- *
- * Comments:
- *
- \*===========================================================================*/
-
- static GDHandle FindDeviceFromWindow(
- WindowPtr window,
- PixMapHandle hPixMap)
- {
- GDHandle device; /* current device */
- Rect devBox; /* local coords of device intersected with drawBox */
- Point topLeft; /* topLeft of current port */
- RgnHandle devRgn; /* region for device rectangle */
- RgnHandle drawRgn; /* region for draw box */
- RgnHandle dstRgn; /* intersect of drawing and device regions */
- Rect drawBox; /* drawing rectangle */
-
- if (!window) {
- return (NULL);
- }
-
- devRgn = NewRgn();
- HLock((Handle)devRgn);
- drawRgn = NewRgn();
- HLock((Handle)drawRgn);
- dstRgn = NewRgn();
- HLock((Handle)dstRgn);
-
- drawBox = window->portRect;
-
- GetPortTopLeft((CGrafPtr)window, &topLeft);
- SetRectRgn(drawRgn,
- drawBox.left, drawBox.top,
- drawBox.right, drawBox.bottom);
-
- device = GetDeviceList();
-
- while (device) {
- if (((*device)->gdFlags & (1 << screenActive))) {
- /* convert the device rect to local coordinates */
- COPYRECT(&(*device)->gdRect, &devBox);
- devBox.top -= topLeft.v;
- devBox.left -= topLeft.h;
- devBox.bottom -= topLeft.v;
- devBox.right -= topLeft.h;
-
- /* test for intersection */
- SetRectRgn(devRgn,
- devBox.left, devBox.top,
- devBox.right, devBox.bottom);
- SectRgn(devRgn, drawRgn, dstRgn);
-
- if (!EmptyRgn(dstRgn)) {
- PixMapHandle gdPMap;
-
- gdPMap = (*device)->gdPMap;
- if ((*gdPMap)->pixelSize == (*hPixMap)->pixelSize) {
- goto GetOutOfThisFunction;
- }
-
- }
- }
-
- device = GetNextDevice(device);
-
- }
-
- GetOutOfThisFunction:
-
- HUnlock((Handle)devRgn);
- HUnlock((Handle)drawRgn);
- HUnlock((Handle)dstRgn);
- DisposeRgn(devRgn);
- DisposeRgn(dstRgn);
- DisposeRgn(drawRgn);
-
- return (device);
- }
-
- /*===========================================================================*\
- *
- * Routine: GetPortTopLeft(port, topLeft)
- *
- * Comments: returns the 0,0 of the port in global coordinates
- *
- \*===========================================================================*/
-
- static void GetPortTopLeft(
- CGrafPtr port,
- Point *topLeft)
- {
- BitMap *bits;
-
- bits = BitsToMap(&((GrafPtr) port)->portBits);
-
- topLeft->v = - bits->bounds.top;
- topLeft->h = - bits->bounds.left;
- }
-
-
- /*===========================================================================*\
- *
- * Routine: BitsToMap(bits)
- *
- * Comments: if bits is the address of portBits of a cgrafport then
- * convert it to a pointer to the port's pix map.
- *
- \*===========================================================================*/
-
- static BitMap *BitsToMap(
- BitMap *bits)
- {
- if (((BitMap *)bits)->rowBytes < 0 &&
- ((BitMap *)bits)->rowBytes & (1 << 14)) {
- bits = *(BitMap **) bits->baseAddr;
- }
-
- return bits;
- }
-